import sys,string
from common import parseArgs
from pygame.locals import *
from ini import ini_file

class ServerInfo(object):
    def __init__(self,name,address,port):
        self.name,self.address,self.port = name,address,int(port)
    def __str__(self):
        return "name=%s\naddress=%s\nport=%s"%(self.name,self.address,self.port)

class ServerFileError(Exception):
    pass

class Servers(dict):
    def __init__(self,fname):
        dict.__init__(self)
        self.fname = fname
        self.parse()
        
    def parse(self):
        fobj = open(self.fname,'r')
        try:
            buf = fobj.read()
        finally:
            fobj.close()
        for dat in buf.split('%%'):
            if not dat: continue
            server_info = self._parse_server(dat)
            self[server_info.name] = self._parse_server(dat)

    def _parse_server(self,dat):
        print repr(dat)
        res = {'name':None,'address':None,'port':None}
        for line in dat.split('\n'):
            if not line or line.startswith("#"):
                continue
            try:
                attr,val = line.split("=",1)
            except ValueError,e:
                raise ServerFileError('Illegal file syntax: %r'%(line,))
            try:    
                if res[attr] is None:
                    print attr,val
                    res[attr] = val
                else:
                    raise ServerFileError('Illegal file syntax duplicate attr: %r'%(line,))
            except KeyError,e:
                raise ServerFileError('Missing:%r'%(attr,))
        for k,v in res.items():
            if v is None:
                raise ServerFileError('Missing:%s'%(k,))
        return ServerInfo(res['name'],res['address'],res['port'])

class SettingsBuilder:
    ' create a settings dict from a inifile and command line args '
    def __init__(self,map_creator,log=sys.stderr,inifile = r"./ini/turb.ini",servers_file=r"./ini/servers.dat"):
        self.log = log
        self.inifile = inifile
        self.map_creator = map_creator
        self.servers_file = servers_file

    def getSettings(self):
        # Create the nested settings dict
        settings = {}
        settings['sound'] = {'on':1,'channels':8}
        settings['network']= {'net_mode':'no_net',
                              'server_addr':None,
                              'server_port':None,
                              'client_port':None}
        settings['graphics'] = {'parallax_layers':0,
                                'flags':0,
                                'bpp':0,
                                'hardware':0,
                                'fullscreen':0,
                                'doublebuff':0}
        settings['game'] = { 'no_of_players':2, 'players':[] }

        # Setup settings with inifile values
        settings = self.__initSettingsFromFile(self.inifile,settings)


        #-------------------------------------------------------
        # Parse Command line
        #-------------------------------------------------------
        (argdict,args) = parseArgs('dfhn:b:p:s:o')
        if args:
            self.log.write("unknown args:%s\n"%args)

        if (argdict.has_key('n') ):
            netopt = argdict['n']
            if netopt[0] == ' ':netopt=netopt[1:]
            if netopt=='server' or netopt =='s':
                settings['network']['net_mode']= 'server'
            elif netopt=='client' or netopt=='c':
                settings['network']['net_mode']= 'client'
            else:
                self.log.write("wrong args!\n")
                sys.exit()
        else:
            settings['network']['net_mode'] = 'no_net'

        if (argdict.has_key('d') ):
            settings['graphics']['doublebuff'] = 1
        if (argdict.has_key('f') ):
            settings['graphics']['fullscreen'] = 1
        if (argdict.has_key('h') ):
            settings['graphics']['hardware'] = 1
        if (argdict.has_key('b') ):
            settings['graphics']['bpp'] = int(argdict['b'])            
        if (argdict.has_key('p') ):
            settings['game']['no_of_players'] = int(argdict['p'])            
        if (argdict.has_key('s') ):
            settings['sound']['on'] = int(argdict['s'])            
        if (argdict.has_key('o') ): import gopsyco

        settings['game']['maps'] = self.map_creator.getAllMapNames()

        return settings

    def __initSettingsFromFile(self,file,settings):
        ' Reads and setup the settings hash from ini file'

        f = ini_file(file)

        # Get the graphics settings
        settings['graphics']['parallax_layers'] = int(f["Graphics"]["ParallaxLayers"])
        SCREEN_W,SCREEN_H = string.split(f["Graphics"]["Reslution"],"x")
        settings['graphics']['res'] = (int(SCREEN_W),int(SCREEN_H))
        settings['graphics']['max_fps'] = int(f["Graphics"]["MaxFPS"])

        # Get the sound settings
        settings['sound']['channels'] = int(f["Sound"]["Channels"])
        settings['sound']['on'] = int(f["Sound"]["On"])
        settings['sound']['FxVol'] = float(f["Sound"]["FxVol"])

        # Get the Network settings
        settings['network']['servers'] = servers = Servers(self.servers_file)
        server = servers[f["Network"]["Server"]]
        settings['network']['server_addr'] = server.address
        settings['network']['server_port'] = server.port
        settings['network']['client_port'] = int(f["Network"]["ClientPort"])


        # Get the Game settings
        settings['game']['map']= f["Game"]["Map"]
        settings['game']['no_of_players'] = int(f["Game"]["Players"])

        # Set up player controls and name
        p = f["Players"].keys()
        p.sort()
        for player in p:
            name = f[player]['Name']
            cont = f[f[player]['Controls']]
            # Convert string def of keys to number
            for key in cont.keys():
                cont[key]=eval(cont[key])

            settings['game']['players'].append({'name':name,'controls':cont})

        return settings
